package org.kca.yarmour.data;

import java.util.ArrayList;
import java.util.List;

import org.kca.yarmour.YAException;
import org.kca.yarmour.data.GlobalData.FactionType;
import org.kca.yarmour.data.GlobalData.TerrainType;
import org.kca.yarmour.yadata.WorldLocationType;

public class WorldLocation
{
    private int row, col;
    private String name, region;
    private String features;
    private boolean named;
    private TerrainType terrain;
    private FactionType faction;
    private Town town;
    /** A list of all quests that can be initiated from this location */
    private List<String> localQuests;
    /** A list of quests which are available for this location because prerequisites have
     * been met. */
    private List<Quest> availableQuests;
    
    public WorldLocation(int row, int col)
    {
        this.row = row;
        this.col = col;
        named = false;
        region = "none";
        faction = FactionType.NONE;
        setTown(null);
        localQuests = new ArrayList<String>();
        availableQuests = new ArrayList<Quest>();
    }

    /**
     * @return the name
     */
    public String getName()
    {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name)
    {
        this.name = name;
        named = (name != null);
    }

    /**
     * @return the faction
     */
    public FactionType getFaction()
    {
        return faction;
    }

    /**
     * @param faction the faction to set
     */
    public void setFaction(FactionType faction)
    {
        this.faction = faction;
    }

    /**
     * @return the region
     */
    public String getRegion()
    {
        return region;
    }

    /**
     * @param region the region to set
     */
    public void setRegion(String region)
    {
        this.region = region;
    }

    /**
     * Gets the terrain type of this location
     * @return the terrain type
     */
    public TerrainType getTerrain()
    {
        return terrain;
    }

    /**
     * @param terrain the terrain to set
     */
    public void setTerrain(TerrainType terrain)
    {
        this.terrain = terrain;
    }

    /**
     * @return the features
     */
    public String getFeatures()
    {
        return features;
    }

    /**
     * @param features the features to set
     */
    public void setFeatures(String features)
    {
        this.features = features;
    }

    /**
     * @return the row coordinate on the map
     */
    public int getRow()
    {
        return row;
    }
    
    /**
     * @return the column coordinate on the map
     */
    public int getCol()
    {
        return col;
    }
    
    /**
     * Checks if this location has its name showing on the world map view
     * @return true if the name is showing
     */
    public boolean isNamed()
    {
        return named;
    }
    
    /**
     * Gets the town in this location, or null if there is no town
     * @return the town
     */
    public Town getTown()
    {
        return town;
    }

    /**
     * Sets the town in this location, or null if there is no town
     * @param town the town to set
     */
    public void setTown(Town town)
    {
        this.town = town;
    }

    /**
     * Gets the list of quests that can spawn at this location
     * @return the local quests
     */
    public List<String> getLocalQuests()
    {
        return localQuests;
    }

    /**
     * Gets the list of available Quests
     * @return the list of available Quests
     */
    public List<Quest> getAvailableQuests()
    {
        return availableQuests;
    }
    
    /**
     * Checks if there is a quest available at this location with the specified id
     * @param qid the quest id
     * @return true if a quest with this id is available
     */
    public boolean hasAvailableQuest(String qid)
    {
        for (Quest q : availableQuests)
        {
            if (q.getId().equals(qid))
            {
                return true;
            }
        }
        return false;
    }


    @Override
    public String toString()
    {
        if (named)
        {
            return name + "(" + row + "," + col + ")";
        }
        else
        {
            return "(" + row + "," + col + ")";
        }
    }
    
    @Override
    public boolean equals(Object o)
    {
        if (o == null || !(o instanceof WorldLocation))
        {
            return false;
        }
        WorldLocation loc = (WorldLocation)o;
        return loc.getRow() == row && loc.getCol() == col;
    }
    
    @Override
    public int hashCode()
    {
        return row * 32767 + col;
    }
    
    public void updateFromXMLType(WorldLocationType wlocType)
    {
        if (wlocType.isNamed())
        {
            setName(wlocType.getName());
        }
        setFaction(FactionType.getFaction(wlocType.getFaction()));
        setRegion(wlocType.getRegion());
        setTerrain(TerrainType.getTerrain(wlocType.getTerrain()));
        if (terrain == null)
        {
            throw new YAException("Illegal terrain type on location " + toString());
        }
        if (faction == null)
        {
            throw new YAException("Illegal faction type on location " + toString());
        }
    }

}
